package com.kcs.dc.report.model.logic;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import com.kcs.common.framework.GenericDto;
import com.kcs.common.utils.ConnectionUtils;
import com.kcs.common.utils.Constant;
import com.kcs.common.utils.ConstantMessage;
import com.kcs.common.utils.EventFactory;
import com.kcs.common.utils.LogWriter;
import com.kcs.common.utils.PropsUtils;
import com.kcs.common.utils.commonUtils;
import com.kcs.dc.report.model.dao.settlementDAO;
import com.kcs.dc.report.model.dao.model.settleInfoModel;
import com.kcs.dc.report.view.dto.MainMenuDto;
import com.kcs.dc.report.view.dto.SettleTodayDto;
import com.kcs.dc.service.bean.request.wsSettleReqBody;
import com.kcs.dc.service.bean.request.wsSettleReqHeader;
import com.kcs.dc.service.bean.request.wsSettleRequest;
import com.kcs.dc.service.bean.response.wsSettleResponseCPT;
import com.kcs.dc.service.impl.wsSettle;

public class settletodayBL {

	private settlementDAO dao = null;
	private Connection conn = null;
	
	public settletodayBL() {
		dao = new settlementDAO();
	}
	
	public GenericDto initEvent(SettleTodayDto dto) throws Exception{
		
		LogWriter.debug("<=====Start init(Settlement Today) Event=====>", Constant.LOGGER_APPLICATION);
		conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
		
		try{
			LogWriter.debug("Step 1 : Check Authorized to use page.", Constant.LOGGER_APPLICATION);
			
			if(!commonBL.checkAuthenUsePage(dto.getUserId(), conn, "config.stm")){
				
				dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_NOHAVE_AUTHEN_PAGE, null);	        	
	        	dto.setService_id("welcome");
	        	
	        	// have error
				MainMenuDto menuDto = new MainMenuDto();
				menuDto.populate(dto);
				return menuDto;	
	        	
			}else{	
				EventFactory event = new EventFactory();
				dto.setChkRevs("S");
				dto = (SettleTodayDto) event.executeBL("settletoday", "search", dto);
			}
	
		}catch(Exception e){
			LogWriter.error("settletodayBL [Method : initEvent] : " + e, Constant.LOGGER_APPLICATION);			
		}finally{
			ConnectionUtils.closeConnection(conn);
		}
		
		
		
		return dto;
	}
	
	private int getInfoDeals(SettleTodayDto dto, Connection conn) throws Exception{
	
		settleInfoModel[] models = null;
		
		int sizeModels = 0;
        
		try{
			models = dao.getInfoDeals(dto.getDealNo(), dto.getIbcCode(),
					dto.getCustName(), dto.getCcy(), dto.getCifNo(), dto.getChkRevs(), "", "",
					conn);
			
	        if (models != null ) { 	
	        	// On screen Grid
				String[] cifDetail = new String[models.length];
				String[] cusNameDetail = new String[models.length];
				String[] ibcCodeDetail = new String[models.length];
				String[] branchDetail = new String[models.length];
				String[] tradNameDetail = new String[models.length];
				String[] prxGroupDetail = new String[models.length];
				String[] prxNameDetail = new String[models.length];
				String[] instrumentDetail = new String[models.length];
				String[] dealNoDetail = new String[models.length];
				String[] parentNoDetail = new String[models.length];
				String[] dealDateDetail = new String[models.length];
				String[] matDateDetail = new String[models.length];
				String[] ccyDetail = new String[models.length];
				String[] buysellDetail = new String[models.length];
				String[] rateDetail = new String[models.length];
				String[] dealAmtDetail = new String[models.length];
				String[] outAmtDetail = new String[models.length];
				String[] setFlagDetail = new String[models.length];
				String[] refDetail = new String[models.length];
				String[] errDetail = new String[models.length];
				String[] errCode = new String[models.length];
				String[] settleAmtDetail = new String[models.length];
				String[] commentDetail = new String[models.length];
				
	        	for (int i = 0; i < models.length; i++) {
	        		cifDetail[i] = models[i].getCif();
	        		cusNameDetail[i] = models[i].getCutName();
	        		ibcCodeDetail[i] = models[i].getIbcCode();
	        		branchDetail[i] = models[i].getBranch();
	        		tradNameDetail[i] = models[i].getMaker_name();
	        		prxGroupDetail[i] = models[i].getProxy_group_fname();
	        		prxNameDetail[i] = models[i].getProxy_fname();
	        		instrumentDetail[i] = models[i].getInstrument();
	        		dealNoDetail[i] = models[i].getDealNo();
	        		parentNoDetail[i] = models[i].getParentNo();
	        		dealDateDetail[i] = commonUtils.convertFormatDate(models[i].getDealDate(), commonUtils.yyyymmdd, commonUtils.ddmmyyyywithslash);
	        		matDateDetail[i] = commonUtils.convertFormatDate(models[i].getMatDate(), commonUtils.yyyymmdd, commonUtils.ddmmyyyywithslash);
	        		ccyDetail[i] = models[i].getCcy();
	        		buysellDetail[i] = models[i].getBuy_sell();
	        		rateDetail[i] = commonUtils.formatNumber(models[i].getExch_rate(), 8, "#",true);
	        		dealAmtDetail[i] = commonUtils.formatNumber(models[i].getDeal_amt(), 2, "0",true);
	        		outAmtDetail[i] = commonUtils.formatNumber(models[i].getOutstd_amt(), 2, "0",true);
	        		settleAmtDetail[i] = outAmtDetail[i];
	        		refDetail[i] = "";
	        		errDetail[i] = "";
	        		errCode[i] = "";
	        		setFlagDetail[i] = "";
	        		commentDetail[i] = "";
				}
	        	
	        	/* Set data to DTO */
	        	dto.setRowIndex(new String[] {});
				dto.setCifDetail(cifDetail);
				dto.setCutNameDetail(cusNameDetail);
				dto.setIbcCodeDetail(ibcCodeDetail);
				dto.setBranchDetail(branchDetail);
				dto.setTradNameDetail(tradNameDetail);
				dto.setPrxGroupDetail(prxGroupDetail);
				dto.setPrxNameDetail(prxNameDetail);
				dto.setInstrumentDetail(instrumentDetail);
				dto.setDealNoDetail(dealNoDetail);
				dto.setParentNoDetail(parentNoDetail);
				dto.setDealDateDetail(dealDateDetail);
				dto.setMatDateDetail(matDateDetail);
				dto.setCcyDetail(ccyDetail);
				dto.setBuysellDetail(buysellDetail);
				dto.setRateDetail(rateDetail);
				dto.setDealAmtDetail(dealAmtDetail);
				dto.setOutstdAmtDetail(outAmtDetail);
				dto.setSettAmtDetail(settleAmtDetail);
				dto.setRefNoDetail(refDetail);
				dto.setErrDetail(errDetail);
				dto.setErrCode(errCode);
				dto.setSettFlagDetail(setFlagDetail);
				dto.setCommentDetail(commentDetail);
				
				sizeModels = models.length;
	        }else{
	        	//clear grid.
	        	clearInfoOnGrid(dto);        	
	        }
	        
		}catch(Exception e){
			LogWriter.error("settletodayBL [Method : getInfoDeals] : " + e, Constant.LOGGER_APPLICATION);
			throw new Exception();
		}
		
		return sizeModels;
	}	

	private void clearInfoOnGrid(SettleTodayDto dto){
		dto.setRowIndex(new String[] {});
		dto.setCifDetail(new String[] {});
		dto.setCutNameDetail(new String[] {});
		dto.setIbcCodeDetail(new String[] {});
		dto.setBranchDetail(new String[] {});
		dto.setTradNameDetail(new String[] {});
		dto.setPrxGroupDetail(new String[] {});
		dto.setPrxNameDetail(new String[] {});
		dto.setInstrumentDetail(new String[] {});		
		dto.setDealNoDetail(new String[] {});
		dto.setParentNoDetail(new String[] {});
		dto.setDealDateDetail(new String[] {});
		dto.setMatDateDetail(new String[] {});
		dto.setCcyDetail(new String[] {});
		dto.setBuysellDetail(new String[] {});
		dto.setRateDetail(new String[] {});
		dto.setDealAmtDetail(new String[] {});
		dto.setOutstdAmtDetail(new String[] {});
		dto.setErrDetail(new String[] {});
		dto.setSettFlagDetail(new String[] {});
		dto.setCommentDetail(new String[] {});
	}

	public GenericDto searchEvent(SettleTodayDto dto) throws Exception{
		LogWriter.debug("<=====Start search(Settlement Today) Event=====>", Constant.LOGGER_APPLICATION);
		
		conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
		
		try{			
			LogWriter.debug("Step 1 : Get information for deal by condition", Constant.LOGGER_APPLICATION);
			int sizeInfo = getInfoDeals(dto, conn);
			
			LogWriter.debug("Length of Information for Settle-Today : " + sizeInfo, Constant.LOGGER_APPLICATION);
			if (sizeInfo == 0){
				// Don't have data.
				dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_NOT_FOUND, null);
				if(!dto.getIbcCode().equals("")) dto.setIbcCode_Attr(Constant.ERR_ATTR);
				if(!dto.getCustName().equals("")) dto.setCustName_Attr(Constant.ERR_ATTR);
				if(!dto.getCcy().equals("")) dto.setCcy_Attr(Constant.ERR_ATTR);
				if(!dto.getCifNo().equals("")) dto.setCifNo_Attr(Constant.ERR_ATTR);
				if(!dto.getDealNo().equals("")) dto.setDealNo_Attr(Constant.ERR_ATTR);
					
			}
			
			dto.setService_id("settletoday");
			
		}catch(Exception e){
			LogWriter.error("settletodayBL [Method : searchEvent] : " + e, Constant.LOGGER_APPLICATION);
		}finally{
			ConnectionUtils.closeConnection(conn);
		}
	
		return dto;	
	}
	
	public GenericDto loadEvent(SettleTodayDto dto) throws Exception{	
		LogWriter.info("<=====Start LoadDeals(Settlement Today) Event=====>", Constant.LOGGER_APPLICATION);
		
		try{
			String jarFile = PropsUtils.getMessage(Constant.PROP_OTHER, "settle.loadbatch.jar") 
					+ " BatchMoveRETtoDCT " 
					+ commonUtils.formatDate(commonUtils.getCurrentDate(), commonUtils.yyyymmdd);
			
			LogWriter.debug("Step 1 : Execute jar file follow path : " + jarFile, Constant.LOGGER_APPLICATION);
	
			Process process = Runtime.getRuntime().exec("java -cp "+jarFile); 
			if (process != null && process.waitFor() == 0 && process.exitValue() == 0){
				LogWriter.debug("Step 2 : Call Search function", Constant.LOGGER_APPLICATION);
							
				EventFactory event = new EventFactory();
				dto = (SettleTodayDto) event.executeBL("settletoday", "search", dto);
				
			}	
		}catch(Exception e){
			LogWriter.error("settletodayBL [Method : loadEvent] : " + e, Constant.LOGGER_APPLICATION);
		}
		return dto;	
			
	}
	
	public GenericDto saveEvent(SettleTodayDto dto) throws Exception{
		LogWriter.info("<=====Start save(Settlement Today) Event=====>", Constant.LOGGER_APPLICATION);
		
		wsSettleReqHeader hd = null;
		wsSettleReqBody[] bdArr = null;
    	wsSettleReqBody bd = null;
    	ArrayList<wsSettleReqBody> arr = new ArrayList<wsSettleReqBody>();
    	HashMap<String, Integer> map = new HashMap<String, Integer>();
    	
    	conn = ConnectionUtils.getConnection(Constant.MSSQL, Constant.TO);
    	
    	try{
			LogWriter.debug("Step 1 : Set Header WSSettleOnline.", Constant.LOGGER_APPLICATION);
			hd = new wsSettleReqHeader();
	    	hd.setNumOfReqRec(dto.getRowIndex().length);
	    	hd.setSystem("DCTT");
	    	hd.setServiceID("WS0002O");
	    	String genReqId = "DCT"
	    				+ commonUtils.formatDate(commonUtils.getCurrentDate(), commonUtils.yyyymmddhhmmss)
	    				+ dto.getUserId().substring(dto.getUserId().length()-3);
	    	hd.setRequestID(genReqId);
	    	LogWriter.debug("@system:'DCTT', @serviceID='WS00020', @requestID='"+genReqId+"', @num_rec="+dto.getRowIndex().length, Constant.LOGGER_APPLICATION);	    	
	    	// ======================================================================== //
	    	
	    	// Prepare variable for keep error.
	    	boolean haveError = false;
	    	String[] errDetail = new String[dto.getDealNoDetail().length];
	    	String[] errCode = new String[dto.getDealNoDetail().length];
	    	
	    	errDetail = dto.getErrDetail();
	    	errCode = dto.getErrCode();
	    	
	    	// ======================================================================== //
	    	
	    	LogWriter.debug("Step 2 : Loop set Body WSSettleOnline.", Constant.LOGGER_APPLICATION);
			for (int i = 0; i < dto.getRowIndex().length; i++) {		    	
				int rowIndex = Integer.valueOf(dto.getRowIndex()[i]);
				
				errDetail[rowIndex] = "";
		    	errCode[rowIndex] = "";
	  	  			
		    	bd = new wsSettleReqBody();
		    	bd.setDealId(dto.getDealNoDetail()[rowIndex]);
		    	// check refNo, setAmt, settleFlag must to specific.
		    	String errMsg = basicCheckBody(dto, dto.getRefNoDetail()[rowIndex], dto.getSettAmtDetail()[rowIndex], dto.getSettFlagDetail()[rowIndex]); 
		    	if(!errMsg.equals("")){
		    		
		    		errDetail[rowIndex] = errMsg;
					errCode[rowIndex] = Constant.ERR_ATTR;
					
					haveError = true;
		    	}else{
		    		bd.setCcyAmt(commonUtils.convertStrtoBigDecimal(dto.getSettAmtDetail()[rowIndex]).doubleValue());
		    	} 	
		    	bd.setSettleFlag(dto.getSettFlagDetail()[rowIndex]);
		    	bd.setSourceRef(dto.getRefNoDetail()[rowIndex]);   	
		    	arr.add(bd);
		    	
		    	LogWriter.debug("@rowIndex='" + rowIndex + "', " +
		    				    "@dealID='"+dto.getDealNoDetail()[rowIndex]+"', " +
		    				    "@settleAmt='"+dto.getSettAmtDetail()[rowIndex]+"', " +
		    				    "@settleFlag='"+dto.getSettFlagDetail()[rowIndex]+"', " +
		    				    "@refNo='" + dto.getRefNoDetail()[rowIndex] +"'", Constant.LOGGER_APPLICATION);
		    	
		    	// Keep key,value to HashMap
		    	if(!map.containsKey(dto.getDealNoDetail()[rowIndex]+"_"+i)){
		    		map.put(dto.getDealNoDetail()[rowIndex]+"_"+i, rowIndex);
		    	}
			}			
		    bdArr = (wsSettleReqBody[]) arr.toArray(new wsSettleReqBody[arr.size()]);
			// ======================================================================== //
		    
		    // Case have error before call web-service then show error screen.
		    if(haveError){
		    	dto.setErrDetail(errDetail);
				dto.setErrCode(errCode);
				
				dto.setService_id("settletoday");
				
				return dto;
		    }
		   // ======================================================================== //
		    
		    // Call WSSettleOnline.
		    wsSettleRequest req = new wsSettleRequest(hd,bdArr);		    	
		    wsSettle settle = new wsSettle();
		    wsSettleResponseCPT res = settle.wsSettle(req);
		    
		    LogWriter.debug("Step 3 : Return response WSSettleOnline.", Constant.LOGGER_APPLICATION);
		    LogWriter.debug("==>Header Response", Constant.LOGGER_APPLICATION);
		    LogWriter.debug("@System : " + res.getHeader().getSystem() + ", " +
			    			"@ServiceID : " + res.getHeader().getServiceID() + ", " +
			    			"@RequestID : " + res.getHeader().getRequestID() + ", " +
			    			"@resp_code : " + res.getHeader().getRespCode() + ", " +
			    			"@resp_desc : " + res.getHeader().getRespDesc() + ", " +
			    			"@respTime : " + res.getHeader().getRespTime(), Constant.LOGGER_APPLICATION);
		       
		    if (res.getHeader().getRespCode().equals("0")){
		    	dto.setMessage(Constant.PROP_REPORT, ConstantMessage.INF_SETTLE_SUCCESS, null);
		    	
		    	LogWriter.debug("Step 4 : Update comment", Constant.LOGGER_APPLICATION);
		    	for (int i = 0; i < dto.getRowIndex().length; i++) {
		    		int rowIndex = Integer.valueOf(dto.getRowIndex()[i]);
					if (dao.updateCommentAndByUserOnDealMovement(
							conn,
							dto.getDealNoDetail()[rowIndex],
							commonUtils.formatDate(commonUtils.getCurrentDate(), commonUtils.yyyymmdd),
							(dto.getSettFlagDetail()[rowIndex].equals("S"))?
									commonUtils.convertStrtoBigDecimal(dto.getSettAmtDetail()[rowIndex]).doubleValue()*(-1)
								   :commonUtils.convertStrtoBigDecimal(dto.getSettAmtDetail()[rowIndex]).doubleValue()*(1),
							genReqId, dto.getRefNoDetail()[rowIndex],
							dto.getCommentDetail()[rowIndex], dto.getUserId())) {
						LogWriter.debug(" Update comment success.", Constant.LOGGER_APPLICATION);
					}
		    		
				}
		    	
		    	LogWriter.debug("Step 5 : Call Search function", Constant.LOGGER_APPLICATION);
				
				EventFactory event = new EventFactory();
				dto = (SettleTodayDto) event.executeBL("settletoday", "search", dto);
		    	
		    }else{
		    	dto.setErrArr(Constant.ERR_ATTR);
		    	dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_SETTLE_FAIL, null);
		    	
		    	LogWriter.debug("==>Body Response(Have Error)", Constant.LOGGER_APPLICATION);  	
				for (int i = 0; i < res.getBody().length; i++) {
					if (res.getBody()[i].getErrStatus().equals("Y")){
						int rowIndex = map.get(res.getBody()[i].getDealId()+"_"+i);
						errDetail[rowIndex] = res.getBody()[i].getErrDesc();  
						errCode[rowIndex] = Constant.ERR_ATTR;
						
					}
			    	LogWriter.debug("@DealId : " + res.getBody()[i].getDealId() + ", " +
			    					"@Source : " + res.getBody()[i].getSourceRef() + ", " +
			    					"@ErrStatus : " + res.getBody()[i].getErrStatus() + ", " +
			    					"@ErrDesc : " + res.getBody()[i].getErrDesc(), Constant.LOGGER_APPLICATION);						
				}	
				
				dto.setErrDetail(errDetail);
				dto.setErrCode(errCode);
		    }
					        
		    dto.setService_id("settletoday");
										
    	}catch(Exception e){
    		LogWriter.error("settletodayBL [Method : saveEvent] : " + e, Constant.LOGGER_APPLICATION);
    	}finally{
			ConnectionUtils.closeConnection(conn);
		}
	
		return dto;
				
	}
	
	private String basicCheckBody(SettleTodayDto dto, String refNo, String settAmt, String set_flag) {

  	 	 // Check Body input.    		   		
		if(refNo.equals("") || settAmt.equals("") || set_flag.equals("") ){
			setErrormsgFromWS(dto);
			return PropsUtils.getMessage(Constant.PROP_REPORT, ConstantMessage.ERR_REF_SETAMT_REQ);
		}else if(!commonUtils.isNumeric(String.valueOf(settAmt))){
			setErrormsgFromWS(dto);
			return PropsUtils.getMessage(Constant.PROP_REPORT, ConstantMessage.ERR_INVALID_FORMAT_NUM);
		}else if(commonUtils.convertStrtoBigDecimal(settAmt).doubleValue() < 0){
			setErrormsgFromWS(dto);
			return PropsUtils.getMessage(Constant.PROP_MESSAGE, ConstantMessage.ERR_AMT_NUMERIC);
	   	}		
  	 
	   	 return "";
	}
	
	private void setErrormsgFromWS(SettleTodayDto dto){
		dto.setErrArr(Constant.ERR_ATTR);
    	dto.setMessage(Constant.PROP_REPORT, ConstantMessage.ERR_SETTLE_FAIL, null);
	}

}
